package middle;

import java.util.Scanner;
import java.util.Stack;

/**
 * JD6 保卫方案
 * @author d3y1
 */
public class JD6{
    private static int N;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        while(in.hasNext()){
            solution(in);
        }
    }

    /**
     * 模拟法: 单调栈
     * @param in
     */
    private static void solution(Scanner in){
        N = in.nextInt();

        // 山峰高度数组
        int[] heights = new int[N];
        for (int i=0; i<N; i++) {
            heights[i] = in.nextInt();
        }

        long result = getVisiblePairs(heights);

        System.out.println(result);
    }

    /**
     * 获取可互见对数: 相邻无重复高度
     * @param heights
     * @return
     */
    public static int getVisiblePairsNoRepeat(int[] heights){
        if (heights == null || N < 2){
            return 0;
        }
        // 除去最高的两座山峰 每一座山峰都可以看见相邻2座山峰 2*(N-2)
        // 最高的两座山峰之间是1对
        // 2*(N-2)+1 = 2*N-3
        return (N*2-3);
    }

    /**
     * 获取可互见对数: 相邻有重复高度
     * @param heights
     * @return
     */
    public static long getVisiblePairs(int[] heights){
        if (N < 2){
            return 0;
        }
        
        // 找到最高山峰索引 从该索引开始遍历
        int maxHeightIndex = 0;
        for (int i=0,size=N; i<size; i++) {
            maxHeightIndex = heights[maxHeightIndex]>heights[i] ? maxHeightIndex:i;
        }
        
        // 单调栈 栈底到栈顶递减
        Stack<Mountain> stack = new Stack<>();
        stack.push(new Mountain(maxHeightIndex,1));
        // 获得最高山峰的下一个索引
        int next = getNextIndex(maxHeightIndex);
        long count = 0;
        Mountain curr;
        while (next != maxHeightIndex){
            // 单调栈循环
            // 当加入的山峰高度会破坏栈的单调性时 弹出栈顶元素
            while (!stack.isEmpty() && heights[stack.peek().index]<heights[next]){
                curr = stack.pop();
                // 往上配对数 + 当前相同高度配对数
                count += curr.num + getCurrHeightPairs(curr.num);
                if(!stack.isEmpty()){
                    // 往下配对数
                    count += curr.num;
                }
            }

            if(!stack.isEmpty() && heights[stack.peek().index]==heights[next]){
                // 山峰高度相同 则增加栈顶元素的num值
                stack.peek().num++;
            }else{
                // 此时加入的山峰不会对栈的单调性造成影响 直接入栈
                stack.push(new Mountain(next,1));
            }
            // 继续向后遍历
            next = getNextIndex(next);
        }

        // 遍历完成后 将栈中剩余元素进行处理 可能依次经历3种阶段
        // 阶段1 栈中剩余元素>2
        while (stack.size() > 2){
            curr = stack.pop();
            // 环形 栈底元素也可看到当前元素(也可配对)
            // 往下配对数 + 栈底配对数 + 当前相同高度配对数
            count += 2*curr.num + getCurrHeightPairs(curr.num);
        }
        // 阶段2 栈中剩余元素=2
        if (stack.size() == 2){
            curr = stack.pop();
            // 当前相同高度配对数 + 往下配对数 + 栈底配对数(栈底元素数量>1)
            count += getCurrHeightPairs(curr.num) + (stack.peek().num==1 ? curr.num : 2*curr.num);
        }
        // 阶段3 栈中剩余元素=1
        if (stack.size() == 1){
            curr = stack.pop();
            count += getCurrHeightPairs(curr.num);
        }

        return count;
    }

    /**
     * 获取当前索引的下一个索引
     * @param index
     * @return
     */
    public static int getNextIndex(int index){
        return (index+1)%N;
    }

    /**
     * 当前相同高度山峰配对数
     * @param num
     * @return
     */
    public static long getCurrHeightPairs(long num){
        return num*(num-1)/2;
    }

    static class Mountain{
        // 山峰高度数组 索引
        public int index;
        // 相同高度山峰个数(相邻)
        public int num;
        public Mountain(int index,int num){
            this.index = index;
            this.num = num;
        }
    }
}